package com.tangsm.spring.boot.async.task;

import com.tangsm.spring.boot.async.domain.UserInfo;
import com.tangsm.spring.boot.async.service.TaskThreadService;
import com.tangsm.spring.boot.async.service.impl.TaskThreadServiceImpl;
import com.tangsm.spring.boot.async.spring.SpringUtils;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.RecursiveTask;

/**
 * 并发任务线程业务处理
 * @author tangsm
 */
public class CustomTaskThread extends RecursiveTask<String> implements Callable<String> {
    private final TaskThreadService taskThreadService;
    private final List<UserInfo> userList;

    public CustomTaskThread(List<UserInfo> userList) {
        this.taskThreadService = SpringUtils.getBean(TaskThreadServiceImpl.class);
        this.userList = userList;
    }

    /**
     * ThreadPoolTaskExecutor 线程池任务执行处理
     *
     * <p>Computes a result, or throws an exception if unable to do so.</p>
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    @Override
    public String call() throws Exception {
        if (CollectionUtils.isEmpty(userList)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        userList.forEach(userInfo -> {
            sb.append(taskThreadService.exec(userInfo)).append(", ");
        });

        return sb.toString();
    }

    /**
     * fork/join 线程池任务执行处理
     *
     * <p>The main computation performed by this task.</p>
     *
     * @return the result of the computation
     */
    @Override
    protected String compute() {
        // 数据大小
        int size = userList.size();

        // 大小等于阈值顺序计算结果
        if (size <= 5) {
            return business();
        }

        // 第一个任务分组
        CustomTaskThread ltTask = new CustomTaskThread(userList.subList(0, size / 2));
        // 第二个任务分组
        CustomTaskThread rtTask = new CustomTaskThread(userList.subList(size / 2, size));

        // 两个任务并发执行起来
        invokeAll(ltTask, rtTask);

        // 读取第一个任务分组处理的结果
        String ltSuccess = ltTask.join();
        // 读取第二个任务分组处理的结果
        String rtSuccess = rtTask.join();

        return ltSuccess + "||" + rtSuccess;
    }

    /**
     * 业务处理
     *
     * @return 结果
     */
    private String business() {
        String result = null;
        try {
            result = call();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
}
